package mygang.controller.manager;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import mygang.controller.AbstractController;
import mygang.dao.manager.ManagerInterface;
import mygang.helper.ControllerHelper;
import mygang.helper.JsonHelper;
import mygang.helper.Utils;
import mygang.model.OptionInterface;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author Volodymyr Lavrynovych <volodya.lavrynovych@gmail.com>
 * date: 06/11/2012
 */
@Controller
public abstract class AbstractManageController<D extends ManagerInterface, T extends OptionInterface> extends AbstractController {
    
    private Logger log = Logger.getLogger(AbstractManageController.class);
    private D service;
    
    /**
     * Prepares data to save
     * @param request contains needed data
     * @return instance of class which is managed
     * @throws Exception 
     */
    abstract T prepareObject(HttpServletRequest request) throws Exception;
    
    /**
     * Returns link to current manage controller
     * @return link to current manage controller
     */
    abstract String getLink();
    
    /**
     * Sets main service
     * @param service defines service
     */
    @Autowired
    public void setService(D service){
        this.service = service;
    }
    
    /**
     * Returns main service
     * @return main service
     */
    public D getService(){
        return service;
    }

    /**
     * Returns manage window
     * @return manage window
     */
    @RequestMapping("/")
    public ModelAndView view(){
        return new ModelAndView(getLink());
    }
    
    /**
     * Returns list of all elements in response
     * @param response contains list of all elements
     * @throws IOException 
     */
    @RequestMapping(value = "/all", method = RequestMethod.POST)
    public void getAll(HttpServletResponse response) throws IOException {
        try {
            JsonHelper.prepareJsonResponse(getService().getAll(), response);
        } catch (Exception ex) {
            ControllerHelper.handleException(ex, response);
        }
    }
    
    /**
     * Returns json list of all elements in response
     * @param response contains json list of all elements
     * @throws IOException 
     */
    @RequestMapping(value = "/jAll", method = RequestMethod.POST)
    public void getAllJson(HttpServletResponse response) throws IOException {
        try {
            JsonHelper.prepareJsonResponse(Utils.convertToOptions(getService().getAll()), response);
        } catch (Exception ex) {
            ControllerHelper.handleException(ex, response);
        }
    }
    
    /**
     * Returns view for add of item
     * @return view for add of item
     */
    @RequestMapping(value = "/a", method = RequestMethod.GET)
    public ModelAndView add(){
        ModelAndView model = new ModelAndView(getLink()+MANAGE_ADD_EDIT_SUFFIX);
        model.addObject("isEdit", false);
        return model;
    }
    
    /**
     * Saves new item
     * @param response contains result for client-side
     * @param request contains all needed data
     * @throws IOException 
     */
    @RequestMapping(value = "/s", method = RequestMethod.POST)
    public void save(HttpServletResponse response, HttpServletRequest request) throws IOException {
        try {
            getService().save(getObject(request));
            ControllerHelper.success(response);
        } catch (Exception ex) {
            ControllerHelper.handleException(ex, response);
        }
    }
    
    /**
     * Returns view for edit of item
     * @param id defines id of item
     * @return view for edit of item
     */
    @RequestMapping(value = "/e", method = RequestMethod.GET)
    public ModelAndView edit(@RequestParam(required = true, value = "id") Long id){
        ModelAndView model = new ModelAndView(getLink()+MANAGE_ADD_EDIT_SUFFIX);
        model.addObject("obj", getService().getById(id.longValue()));
        model.addObject("isEdit", true);
        return model;
    }
    
    /**
     * Deletes item by id
     * @param response contains result for client-side
     * @param request contains id of item to delete
     * @throws IOException 
     */
    @RequestMapping(value = "/d", method = RequestMethod.POST)
    public void delete(HttpServletResponse response, HttpServletRequest request) throws IOException{
        try {
            long id = new Long(request.getParameter("id")).longValue();
            getService().delete(id);
            ControllerHelper.success(response);
        } catch (Exception ex) {
            ControllerHelper.handleException(ex, response);
        }
    }
    
    /**
     * Returns prapared object
     * @param request contains data
     * @return prapared object
     * @throws Exception 
     */
    protected T getObject(HttpServletRequest request) throws Exception{
        printParameters(request);
        return prepareObject(request);
    }
}